package com.spzx.cart.service.impl;

import com.spzx.cart.api.domain.CartInfo;
import com.spzx.cart.service.ICartService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.api.domain.vo.SkuPrice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CartServiceImpl implements ICartService {

    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    private RemoteProductService remoteProductService;
    /**
     * 添加购物车
     */
    public String getCartKey(Long userId){
        return "user:cart:"+userId;
    }
    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        String hashKey = skuId.toString();
        Integer threshold =99;
        if (hashOps.hasKey(hashKey)) {
            CartInfo cartInfo = hashOps.get(hashKey);
            int totalCount = cartInfo.getSkuNum() + skuNum;
            cartInfo.setSkuNum(totalCount > threshold ? threshold : totalCount);
            hashOps.put(hashKey,cartInfo);
        }else {
            Long size = hashOps.size();
            if (++size > 50) {
                throw new ServiceException("商品种类数量超过上限");
            }
            CartInfo cartInfo = new CartInfo();
            cartInfo.setUserId(userId);
            cartInfo.setSkuId(skuId);
            R<SkuPrice> skuPrice = remoteProductService.getSkuPrice(skuId, SecurityConstants.INNER);
            if (R.FAIL == skuPrice.getCode()) {
                throw new ServiceException(skuPrice.getMsg());
            }
            SkuPrice skuPriceData = skuPrice.getData();
            cartInfo.setSkuPrice(skuPriceData.getSalePrice());
            cartInfo.setCartPrice(skuPriceData.getSalePrice());
            cartInfo.setSkuNum(skuNum > threshold ? threshold : skuNum);
            R<ProductSku> productSku = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
            if (R.FAIL == productSku.getCode()) {
                throw new ServiceException(productSku.getMsg());
            }
            ProductSku productSkuData = productSku.getData();
            cartInfo.setThumbImg(productSkuData.getThumbImg());
            cartInfo.setCreateTime(new Date());
            cartInfo.setUpdateTime(new Date());
            hashOps.put(hashKey,cartInfo);
        }
    }

    @Override
    public List<CartInfo> getCartList() {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            List<Long> skuIdList = cartInfoList.stream().map(CartInfo::getSkuId).toList();
            R<List<SkuPrice>> skuPriceList = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
            if (R.FAIL==skuPriceList.getCode()) {
                throw new ServiceException(skuPriceList.getMsg());
            }
            List<SkuPrice> priceListData = skuPriceList.getData();
            Map<Long, BigDecimal> skuIdToSalePriceMap = priceListData.stream().
                    collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));
            for (CartInfo cartInfo : cartInfoList) {
                cartInfo.setSkuPrice(skuIdToSalePriceMap.get(cartInfo.getSkuId()));
            }
            return cartInfoList;
        }
        return new ArrayList<>();
    }

    @Override
    public void deleteCart(Long skuId) {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        if (hashOps.hasKey(skuId.toString())) {
            hashOps.delete(skuId.toString());
        }
    }

    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        if (hashOps.hasKey(skuId.toString())) {
            CartInfo cartInfo = hashOps.get(skuId.toString());
            cartInfo.setIsChecked(isChecked);
            hashOps.put(skuId.toString(),cartInfo);
        }
    }

    @Override
    public void allCheckCart(Integer isChecked) {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        if (hashOps.size()>0) {
            List<CartInfo> cartInfoList = hashOps.values();
            for (CartInfo cartInfo : cartInfoList) {
                cartInfo.setIsChecked(isChecked);
                hashOps.put(cartInfo.getSkuId().toString(),cartInfo);
            }
        }
    }

    @Override
    public void clearCart() {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        if (redisTemplate.hasKey(cartKey)) {
            redisTemplate.delete(cartKey);
        }
    }

    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        List<CartInfo> cartInfoList=new ArrayList<>();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfos = hashOps.values();
        if (!CollectionUtils.isEmpty(cartInfos)) {
            for (CartInfo cartInfo : cartInfos) {
                if (cartInfo.getIsChecked()==1) {
                    cartInfoList.add(cartInfo);
                }
            }
        }
        return cartInfoList;
    }

    @Override
    public Boolean updateCartPrice(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            List<Long> skuIdList = cartInfoList.stream().map(CartInfo::getSkuId).toList();
            R<List<SkuPrice>> skuPriceList = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
            if (R.FAIL==skuPriceList.getCode()){
                throw new ServiceException(skuPriceList.getMsg());
            }
            List<SkuPrice> priceListData = skuPriceList.getData();
            Map<Long, BigDecimal> bigDecimalMap = priceListData.stream().
                    collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));
            for (CartInfo cartInfo : cartInfoList) {
                if (cartInfo.getIsChecked()==1){
                    cartInfo.setCartPrice(bigDecimalMap.get(cartInfo.getSkuId()));
                    cartInfo.setSkuPrice(bigDecimalMap.get(cartInfo.getSkuId()));
                    hashOps.put(cartInfo.getSkuId().toString(),cartInfo);
                }
            }
        }
        return true;
    }

    @Override
    public Boolean deleteCartCheckList(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            for (CartInfo cartInfo : cartInfoList) {
                if (cartInfo.getIsChecked()==1){
                    hashOps.delete(cartInfo.getSkuId().toString());
                }
            }
        }
        return true;
    }
}